package com.ge.modules.api.controller;


import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.ge.common.annotation.AuthIgnoreApi;
import com.ge.common.annotation.LoginUserApi;
import com.ge.common.utils.AliPayUtils;
import com.ge.common.utils.DateUtils;
import com.ge.common.utils.R;
import com.ge.modules.api.service.TbOrderHeaderService;
import com.ge.modules.api.service.TbOrderService;
import com.ge.modules.api.service.TbRechargeOrderService;
import com.ge.modules.api.service.TbUserCardService;
import com.ge.modules.entity.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * 支付控制器
 */
@RestController
@RequestMapping("/api/user/alipay")
public class TbAIlPayController {

    @Autowired
    private TbOrderHeaderService orderHeaderService;

    @Autowired
    private TbRechargeOrderService rechargeOrderService;

    @Autowired
    private TbUserCardService userCardService;

    @Autowired
    private TbOrderService tbOrderService;


    /**
     * 商品订单阿里支付
     *
     * @param tbOrder
     * @return
     */
    @AuthIgnoreApi
    @RequestMapping("/payOrder")
    public String payOrder(TbOrderEntity tbOrder) {
        //实例化客户端
        AlipayClient alipayClient = new DefaultAlipayClient(AliPayUtils.URL, AliPayUtils.APP_ID, AliPayUtils.APP_PRIVATE_KEY, AliPayUtils.FORMAT, AliPayUtils.CHARSET, AliPayUtils.ALIPAY_PUBLIC_KEY, AliPayUtils.SIGN_TYPE);
        //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称：alipay.trade.app.pay
        AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
        //SDK已经封装掉了公共参数，这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
        AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
        model.setBody("the data is true");
        model.setSubject("向GE平台发起支付");
        //拼接商品订单标识
        model.setOutTradeNo(AliPayUtils.ORDER_PAY + tbOrder.getOrderCode());
        model.setTimeoutExpress("30m");
        model.setTotalAmount("" + tbOrder.getOrderPrice());
        model.setProductCode("QUICK_MSECURITY_PAY");
        request.setBizModel(model);
        request.setNotifyUrl(AliPayUtils.ALIPAY_NOTIFYURL);
        try {
            //这里和普通的接口调用不同，使用的是sdkExecute
            AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
            System.out.println(">>>>>>>>" + response.getBody());//就是orderString 可以直接给客户端请求，无需再做处理。
            return response.getBody();
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 充值订单阿里支付
     *
     * @param tbRechargeOrderEntity
     * @return
     */
    @AuthIgnoreApi
    @RequestMapping("/payRechargeOrder")
    public String payRechargeOrder(TbRechargeOrderEntity tbRechargeOrderEntity) {
        //实例化客户端
        AlipayClient alipayClient = new DefaultAlipayClient(AliPayUtils.URL, AliPayUtils.APP_ID, AliPayUtils.APP_PRIVATE_KEY, AliPayUtils.FORMAT, AliPayUtils.CHARSET, AliPayUtils.ALIPAY_PUBLIC_KEY, AliPayUtils.SIGN_TYPE);
        //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称：alipay.trade.app.pay
        AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
        //SDK已经封装掉了公共参数，这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
        AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
        model.setBody("the data is true");
        model.setSubject("向GE平台发起支付");
        //拼接充值订单标识
        model.setOutTradeNo(AliPayUtils.BALANCE_PAY + tbRechargeOrderEntity.getRechargeOrderCode());
        model.setTimeoutExpress("30m");
        model.setTotalAmount("" + tbRechargeOrderEntity.getMoney());
        model.setProductCode("QUICK_MSECURITY_PAY");
        request.setBizModel(model);
        request.setNotifyUrl(AliPayUtils.ALIPAY_NOTIFYURL);
        try {
            //这里和普通的接口调用不同，使用的是sdkExecute
            AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
            return response.getBody();
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 余额支付接口
     *
     * @param tbUser
     * @param orderCode 订单编号
     * @param orderType 订单类型 GOODS_ORDER RECHARGE_ORDER
     * @return
     */
    @PostMapping("balancePay")
    public R balancePay(@LoginUserApi TbUser tbUser, String orderCode, String orderType) {
        //查询用户会员卡信息
        TbUserCardEntity tbUserCardEntity = new TbUserCardEntity();
        tbUserCardEntity.setUserId(tbUser.getUserId());
        TbUserCardEntity userCard = userCardService.queryByObject(tbUserCardEntity);
        //判断是商品订单 还是余额订单
        if (orderType.equals(AliPayUtils.goodsOrder)) {
            System.out.println(">>>>>>>>进入商品订单");
            //2 查询系统中是否存在商品订单
            TbOrderHeaderEntity tbOrderHeaderEntity = orderHeaderService.queryObject(new TbOrderHeaderEntity(orderCode));
            TbOrderEntity tbOrderEntity = tbOrderService.queryObject(new TbOrderEntity(orderCode));
            if (tbOrderHeaderEntity != null) {
                System.out.println(">>>>>>>>进入父商品订单");
                tbOrderHeaderEntity.setOderheaderStatus(1);
                tbOrderHeaderEntity.setOrderPayType(1);
                tbOrderHeaderEntity.setOrderPayType(0);
                //判断用户余额是否大于订单支付的金额
                if (userCard.getBalance().compareTo(tbOrderHeaderEntity.getOrderheaderPrice()) == -1) {
                    return R.error("用户余额不足！");
                }
                //余额减去支付金额
                userCard.setBalance(userCard.getBalance().subtract(tbOrderHeaderEntity.getOrderheaderPrice()));
                orderHeaderService.updateOrderAndUserCard(tbOrderHeaderEntity, userCard);
            } else if (tbOrderEntity != null) {
                System.out.println(">>>>>>>>进入子商品订单");
                tbOrderEntity.setOrderStatus(1);
                tbOrderEntity.setOrderpayType(0);
                //判断用户余额是否大于订单支付的金额
                if (userCard.getBalance().compareTo(tbOrderEntity.getOrderPrice()) == -1) {
                    return R.error("用户余额不足！");
                }
                //余额减去支付金额
                userCard.setBalance(userCard.getBalance().subtract(tbOrderEntity.getOrderPrice()));
                tbOrderService.updateOrderAndUserCard(tbOrderEntity, userCard);
            } else {
                return R.error("没有订单");
            }
        } else if (orderType.equals(AliPayUtils.rechargeOrder)) {
            //根据订单编号查询余额订单
            TbRechargeOrderEntity tbRechargeOrderEntity = new TbRechargeOrderEntity();
            tbRechargeOrderEntity.setRechargeOrderCode(orderCode);
            TbRechargeOrderEntity rechargeOrderEntity = rechargeOrderService.queryByObject(tbRechargeOrderEntity);
            //判断用户余额是否大于订单支付的金额
            if (userCard.getBalance().compareTo(rechargeOrderEntity.getMoney()) == -1) {
                return R.error("用户余额不足！");
            }
            //余额减去支付金额
            userCard.setBalance(userCard.getBalance().subtract(rechargeOrderEntity.getMoney()));
            //计算和修改用户会员卡时间
            commentFunction(userCard, rechargeOrderEntity);
            //改为以支付
            rechargeOrderEntity.setPayStatus(2);
            rechargeOrderEntity.setPayType(0);
            userCardService.updateSomeThing(userCard, rechargeOrderEntity);
        }
        return R.ok().put("data","成功");
    }

    /**
     * 异步回调地址
     *
     * @param request
     * @return
     * @throws IOException
     */
    @AuthIgnoreApi
    @RequestMapping("/aliPayNotify")
    public String aliPayNotify(HttpServletRequest request) throws IOException {
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>进回调了");
        //获取支付宝POST过来反馈信息
        Map<String, String> params = new HashMap<String, String>();
        Map requestParams = request.getParameterMap();
        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            //乱码解决，这段代码在出现乱码时使用。
            //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }
        try {
            System.out.println(">>>>>>>>>>>>>>>>>>" + params.get("out_trade_no"));

            boolean flag = AlipaySignature.rsaCheckV1(params, AliPayUtils.ALIPAY_PUBLIC_KEY, params.get("charset"), AliPayUtils.SIGN_TYPE);
            //状态TRADE_SUCCESS的通知触发条件是商户签约的产品支持退款功能的前提下，买家付款成功；
            //交易状态TRADE_FINISHED的通知触发条件是商户签约的产品不支持退款功能的前提下，买家付款成功；或者，商户签约的产品支持退款功能的前提下，交易已经成功并且已经超过可退款期限。
            if (!flag) {
                //1 验证app_id是否为该商户本身。
                if (!params.get("app_id").equals(AliPayUtils.APP_ID)) {
                    return "failure";
                }
                String orderCodeAdd = params.get("out_trade_no");
                String[] orderCodes = orderCodeAdd.split("\\|");
                //订单标识
                String order_sign = orderCodes[0];
                //订单编号
                String orderCode = orderCodes[1];
                //判断是商品订单还是余额订单
                //商品订单
                if (AliPayUtils.ORDER_PAY.equals(order_sign + "|")) {
                    System.out.println("+++++++++++" + "进入商品订单");
                    //2 查询系统中是否存在商品订单
                    TbOrderHeaderEntity tbOrderHeaderEntity = orderHeaderService.queryObject(new TbOrderHeaderEntity(orderCode));
                    TbOrderEntity tbOrderEntity = tbOrderService.queryObject(new TbOrderEntity(orderCode));
                    //判断是支付的主订单还是子订单
                    if (tbOrderHeaderEntity != null) {
                        //3 判断金额是否正确
                        if (tbOrderHeaderEntity.getOrderheaderPrice().compareTo(new BigDecimal(params.get("total_amount"))) != 0) {
                            return "failure";
                        }
                        //4 校验通知中的seller_id（或者seller_email) 是否为out_trade_no这笔单据的对应的操作方（有的时候，一个商户可能有多个seller_id/seller_email）
                        if ("TRADE_SUCCESS".equals(params.get("trade_status"))) {
                            //使用线程实现的好处可以及时向 支付宝or微信返回消息 自己的业务逻辑 线程自己跑
                            //坏处是 要是自己内部报错 就不能重新获取通知了
                            //暂不使用线程
//                        new Thread(() -> {
//                        }).start();
                            //修改主订单和子订单的支付状态
                            tbOrderHeaderEntity.setOderheaderStatus(1);
                            tbOrderHeaderEntity.setOrderPayType(1);
                            orderHeaderService.updateOrderPayStatus(tbOrderHeaderEntity);
                        }
                    } else if (tbOrderEntity != null) {
                        //3 判断金额是否正确
                        if (tbOrderEntity.getOrderPrice().compareTo(new BigDecimal(params.get("total_amount"))) != 0) {
                            return "failure";
                        }
                        //4 校验通知中的seller_id（或者seller_email) 是否为out_trade_no这笔单据的对应的操作方（有的时候，一个商户可能有多个seller_id/seller_email）
                        if ("TRADE_SUCCESS".equals(params.get("trade_status"))) {
                            //子订单的支付状态 为待接单
                            tbOrderEntity.setOrderStatus(1);
                            tbOrderService.update(tbOrderEntity);
                        }
                    } else {
                        return "failure";
                    }
                    return "success";
                }
                //余额订单
                else if (AliPayUtils.BALANCE_PAY.equals(order_sign + "|")) {
                    System.out.println("+++++++++++" + "进入余额订单");
                    TbRechargeOrderEntity tbRechargeOrderEntity = new TbRechargeOrderEntity();
                    tbRechargeOrderEntity.setRechargeOrderCode(orderCode);
                    TbRechargeOrderEntity rechargeOrderEntity = rechargeOrderService.queryByObject(tbRechargeOrderEntity);
                    //2 查询系统中是否存在余额订单
                    if (rechargeOrderEntity == null) {
                        return "failure";
                    }
                    //3 判断金额是否正确
                    if (rechargeOrderEntity.getMoney().compareTo(new BigDecimal(params.get("total_amount"))) != 0) {
                        return "failure";
                    }
                    //4 校验通知中的seller_id（或者seller_email) 是否为out_trade_no这笔单据的对应的操作方（有的时候，一个商户可能有多个seller_id/seller_email）
                    //查询用户会员卡信息
                    TbUserCardEntity tbUserCardEntity = new TbUserCardEntity();
                    tbUserCardEntity.setUserId(rechargeOrderEntity.getUserId());
                    TbUserCardEntity userCard = userCardService.queryByObject(tbUserCardEntity);
                    //计算和修改用户会员卡时间
                    commentFunction(userCard, rechargeOrderEntity);
                    //如果充值的是余额就增加会员卡余额
                    if (rechargeOrderEntity.getRechargeType() == 0) {
                        userCard.setBalance(userCard.getBalance().add(rechargeOrderEntity.getMoney()));
                    }
                    rechargeOrderEntity.setPayStatus(2);
                    rechargeOrderEntity.setPayType(1);
                    //修改
                    userCardService.updateSomeThing(userCard, rechargeOrderEntity);
                } else {
                    return "failure";
                }
            } else {
                return "failure";
            }
        } catch (AlipayApiException e) {
//            LOGGER.error("支付宝回调验证错误,错误码{},错误消息{}", e.getErrCode(), e.getErrMsg());
            return "failure";
        }
        return "failure";
    }

    public TbUserCardEntity commentFunction(TbUserCardEntity userCard, TbRechargeOrderEntity rechargeOrderEntity) {
        //判断余额充值类型 0 余额 1 月卡 2 年卡
        int reChargeType = rechargeOrderEntity.getRechargeType();
        //月卡 更新用户会员卡月卡更新时间
        if (reChargeType == 1) {
            //如果用户是年卡会员 则不修改为月卡会员
            if (userCard.getCardType() != 2) {
                userCard.setCardType(1);
            }
            //月卡结束时间
            Date monthCardEndTime = userCard.getMonthCardEndTime();
            //当前月卡的结束时间是否大于当前时间
            // 是 就没有过期 就在当前月卡结束日期上叠加
            // 否 就过期了 就更新月卡的开始时间和结束时间
            Boolean bo = DateUtils.date_compare_date(monthCardEndTime, new Date());
            //没有过期
            if (bo) {
                //一个月按30天计算 根据月卡结束日期开始加算一个月按30天计算
                Date newMonthCardEndTime = DateUtils.dataAdd(monthCardEndTime, 30);
                userCard.setMonthCardEndTime(newMonthCardEndTime);
            }
            //过期了
            else {
                //一个月按30天计算 根据当前日期开始加算一个月按30天计算
                Date newMonthCardEndTime = DateUtils.dataAdd(new Date(), 30);
                userCard.setMonthCardStartTime(new Date());
                userCard.setMonthCardEndTime(newMonthCardEndTime);
            }
        }
        //年卡 更新用户会员卡年卡更新时间
        else if (reChargeType == 2) {
            //修改卡类型为年卡
            userCard.setCardType(2);
            //年卡结束时间
            Date yearCardEndTime = userCard.getYearCardEndTime();
            //当前年卡的结束时间是否大于当前时间
            // 是 就没有过期 就在当前年卡结束日期上叠加
            // 否 就过期了 就更新年卡的开始时间和结束时间
            Boolean bo = DateUtils.date_compare_date(yearCardEndTime, new Date());
            //没有过期
            if (bo) {
                //一年按365天计算 根据年卡结束日期开始加算一个年按365天计算
                Date newYearCardEndTime = DateUtils.dataAdd(yearCardEndTime, 365);
                userCard.setYearCardEndTime(newYearCardEndTime);
            }
            //过期了
            else if (!bo) {
                //一年按365天计算 根据当前日期开始加算一年按365天计算
                Date date = new Date();
                Date newYearCardEndTime = DateUtils.dataAdd(date, 365);
                userCard.setYearCardStartTime(date);
                userCard.setYearCardEndTime(newYearCardEndTime);
            }
        }
        return userCard;
    }

    public static void main(String[] args) {
        new Thread(() -> {
            for (int i = 0; i < 20; i++) {
                System.out.println(i);
            }
        }).start();
        System.out.println("线程结束");
    }
}
